Módulo 2: Estructuración y manipulación de datos con Python#
El manejo de datos es el corazón de cualquier proyecto de análisis, y Python se ha consolidado como uno de los lenguajes más poderosos y versátiles para este propósito. En este módulo, nos sumergiremos en las técnicas fundamentales para la estructuración y manipulación de datos utilizando Python, proporcionando las bases necesarias para transformar datos crudos en información útil y procesable.
Comenzaremos explorando las estructuras de datos disponibles en Python, como listas, dataframes, pilas, colas, árboles y grafos. Estas estructuras permiten organizar y acceder a la información de manera eficiente, lo que es crucial cuando se trabaja con grandes volúmenes de datos o datos complejos. Además, abordaremos cómo manipular y transformar datos no estructurados, como textos, imágenes y datos provenientes de redes sociales, que requieren enfoques y herramientas específicas para su análisis.
El módulo también se centrará en el uso de librerías especializadas como NumPy y Pandas, que son esenciales para el análisis de datos en Python. Estas librerías ofrecen potentes funciones para la manipulación y el análisis de datos estructurados, permitiendo realizar operaciones avanzadas con facilidad y eficiencia.
Además, aprenderemos a trabajar con secuencias de datos utilizando herramientas como re, string e itertools, que son fundamentales para el procesamiento y análisis de cadenas de texto y otras secuencias de información. La habilidad para manipular secuencias es clave en tareas como la limpieza de datos y la preparación de datos para modelos de machine learning.
Finalmente, exploraremos las bases de la visualización de datos para representar de manera gráfica los resultados del análisis, facilitando la interpretación y comunicación de los hallazgos. Este módulo también incluirá casos prácticos que permitirán a los participantes aplicar las técnicas aprendidas en escenarios reales, consolidando así los conceptos y habilidades adquiridos.
Archivos planos con Numpy y Pandas#
En esta sección aprenderás a importar datos a Python desde todo tipo de archivos planos, que son una forma sencilla y frecuente de almacenamiento de datos. Ya has aprendido a utilizar NumPy y Pandas: aprenderás a utilizar estos paquetes para importar archivos planos y personalizar tus importaciones.
Archivos planos#
Los archivos de texto plano se pueden clasificar en dos grandes tipos:
Archivos que contienen texto sin formato . Por ejemplo:

Archivos que contienen registros estructurados. Un ejemplo es el conjunto de datos del Titanic

En este archivo, cada columna representa una característica o rasgo, como el género, la cabina o si la persona sobrevivió, mientras que cada fila corresponde a una persona que estaba a bordo del Titanic.
Es fundamental que cualquier científico de datos comprenda el concepto de archivo plano. Estos son archivos de texto simples que contienen datos organizados en tablas, pero sin relaciones estructuradas complejas.
Es probable que hayas notado que la extensión del archivo es .csv. Tal vez te preguntes qué significa:
.csv(Comma-Separated Values): Archivo en el que los valores están separados por comas..txt: Archivo de texto simple..tsv(Tab-Separated Values): Archivo en el que los valores están separados por tabulaciones.
Los valores en archivos planos pueden estar separados por diferentes caracteres, como comas o tabulaciones, conocidos como delimitadores. Estos delimitadores permiten organizar y estructurar los datos de manera sencilla y efectiva.
Ahora, para consultar cualquier archivo de texto sin formato, que debemos hacer:
Asignar el nombre del archivo a una variable como una cadena.
Usamos la función básica
opende Python para abrir una conexión al archivo y le pasamos el argumentomode='r', lo que garantiza que solo podamos leerlo.Despues le asignamos el texto del archivo a una variable
textaplicando el métodoreada la conexión al archivo.Después asegúrese de cerrar la conexión al archivo usando el comando
file.close.
Miremos un ejemplo:
# Ejemplo
Puedes evitar tener que cerrar la conexión al archivo utilizando una declaración with. Esto le permite crear un contexto en el que puede ejecutar comandos con el archivo abierto. Una vez fuera de esta cláusula o contexto, el archivo ya no está abierto y, por esta razón, with se denomina administrador de contexto. Realmente asegura que el archivo se cierre correctamente, incluso si ocurre un error durante la escritura. Por ejemplo:
# Ejemplo
Ejercicios
Abre el archivo de texto
GabrielGarciaMarquez.txte imprimelo. Utiliza el administrador de contextowith.En el caso de archivos grandes, puede que no queramos imprimir todo su contenido en el shell: tal vez quieras imprimir sólo las primeras líneas. Use el archivo de texto
GabrielGarciaMarquez.txte imprima las 3 primeras líneas. Sugerencia: use el métodoreadline().
Importación y exportación de archivos planos con Numpy#
Ahora que sabes cómo usar la función incorporada open de Python para abrir archivos de texto, veamos cómo importar un archivo plano y asignarlo a una variable. Si todos los datos son numéricos, puedes usar el paquete NumPy para importarlos como una matriz NumPy. ¿Por qué querríamos hacer esto?
Características de las matrices NumPy
Eficiencia y velocidad:
Las matrices NumPy son el estándar de Python para almacenar datos numéricos debido a su eficiencia y rapidez.
Son ideales para manejar grandes volúmenes de datos de manera limpia y ordenada.
Compatibilidad con otros paquetes:
NumPy es esencial para muchos otros paquetes en Python, como
scikit-learn, un popular paquete de aprendizaje automático.
Al trabajar con scikit-learn, es común que los datos estén en formato de matriz NumPy.
NumPy tiene varias funciones integradas que nos permiten importar datos como matrices de forma mucho más sencilla y eficiente. Aquí se encuentran las funciones loadtxt y genfromtxt.
loadtxt: Importa datos de un archivo de texto como una matriz NumPy. Por ejemplo
# dataset
# mnist es una colección de dígitos manuscritos del 0 al 9
# Ejemplo
Algunos argumentos adicionales de loadtxt
skiprows: Si deseas omitir la primera fila (por ejemplo, un encabezado), puedes usarskiprows=1.
# Ejemplo
usecols: Si solo quieres importar columnas específicas, usausecolscon una lista de los índices de las columnas.
# Ejemplo
dtype: Te ayuda a importar diferentes tipos de datos en matrices.dtype=strgarantiza que todas las entradas se importen como cadenas
# Ejemplo
genfromtxt: Similar a
loadtxt, pero más flexible para manejar datos mixtos. Además, cuando usamosdtype=Nonepermite que NumPy adivine el tipo de datos para cada columna. Por ejemplo:
# Ejemplo
Ejercicios
Del archivo digitos.txt, que tiene la primera fila con los nombres de las variables y está delimitado por tabulaciones. Importe solo las 3 primeras columnas del archivo plano. Imprime la primera fila
Ahora, para exportar archivos planos usando NumPy, puedes utilizar la función numpy.savetxt(). Esta función es muy útil para guardar datos en un archivo de texto con un formato específico. Aquí te muestro un ejemplo básico:
# Crear una matriz NumPy
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# Ejemplo
Una breve explicación de los parámetros es la siguiente:
'archivo.txt': Nombre del archivo en el que se guardarán los datos.data: La matrizNumPyque deseas guardar.fmt='%d': El formato en el que los datos se guardarán (en este caso, enteros). Puedes ajustar el formato según el tipo de datos que estás manejando (por ejemplo, %.2f para números de punto flotante con dos decimales).delimiter=',': El delimitador que separa los valores en el archivo. Aquí se usa una coma, pero puedes cambiarlo a otro carácter como un espacio' 'o un punto y coma';'.
Si quieres agregar un encabezado al archivo, puedes hacerlo con el parámetro header:
# Ejemplo
Importación y exportación de archivos planos con Pandas#
En la ciencia de datos, se requiere manejar estructuras de datos etiquetadas bidimensionales con columnas de tipos potencialmente diferentes, algo que las matrices NumPy no pueden satisfacer completamente. Esta necesidad impulsó a Wes McKinney a desarrollar la biblioteca Pandas para Python, que se ha convertido en una herramienta esencial para los científicos de datos.
Pandas es una biblioteca de Python que permite llevar a cabo todo el flujo de trabajo de análisis de datos sin cambiar a otro lenguaje específico como R. La estructura de datos más relevante en Pandas es el DataFrame, que es el análogo Pythonic del marco de datos en R.
Características claves de Pandas
Importación de datos:
Pandasfacilita la importación de archivos planos, bases de datos, archivos Excel, entre otros, como DataFrames.Estructuras de datos etiquetadas: Los DataFrames permiten manipular y analizar datos con etiquetas en filas y columnas, lo que facilita el manejo de diferentes tipos de datos en un solo lugar.
Manipulación de datos:
Pandasofrece funciones para cortar, remodelar, agrupar, unir y fusionar datos de manera eficiente.Estadísticas y manejo de valores faltantes: Realiza cálculos estadísticos sin afectar los valores faltantes y proporciona herramientas para manejar series temporales.
Ahora importemos un archivo plano con Pandas:
# Importar un archivo CSV como DataFrame
# Ejemplo
También podemos convertir fácilmente el DataFrame en una matriz numpy.
# Ejemplo
Ejercicios
Importe el dataset del
titanic.csv, guardelo en el objetodfy muestre las 5 ultimas filas.Completa el código:
# Asignar el nombre de archivo: file
file = 'digitos.csv'
# Leer las primeras 5 filas del archivo en un DataFrame: data
# Use nrow y header
# TU CODIGO
# Construir un de numpy a partir del DataFrame: data_array
# TU CODIGO
# Imprimir el tipo de dato de data_array en la consola
print(type(data_array))
Complete el código:
# Asignar el nombre del archivo: file
file = 'titanic_corrupt.txt'
# Importar el archivo: data
data = pd.read_csv(file, sep=____, comment=____, na_values=____)
# Imprimir las primeras filas del DataFrame
print(data.head())
donde
sep=es el delimitador que separa los campos en el archivo (en tu caso, debería ser'\t'o',').comment=especifica el carácter que indica el inicio de un comentario (en tu caso, debería ser'#').na_values=define los valores que deben ser interpretados como valores faltantes (puedes usar `’NA’, 0 ‘NaN’ o ‘Nothing’).
Ahora, para exportar archivos planos usando pandas, puedes utilizar la función to_csv() para guardar datos en formato CSV. Aquí te muestro cómo hacerlo para archivos CSV y otros formatos comunes:
# Crear un DataFrame
data = {
'Columna1': [1, 4, 7],
'Columna2': [2, 5, 8],
'Columna3': [3, 6, 9]
}
df = pd.DataFrame(data)
# Guardar el DataFrame en un archivo CSV
# Ejemplo
Una breve explicación de los parámetros de to_csv():
'archivo.csv': Nombre del archivo CSV a generar.index=False: Evita que se guarde la columna de índices del DataFrame en el archivo CSV.
Puedes usar to_csv() con diferentes delimitadores para crear archivos de texto con otros formatos:
# Ejemplo
Importación e exportación de datos de otros tipos de archivos#
Como científico de datos, es crucial saber cómo importar datos desde una variedad de tipos de archivo. En esta sección, exploraremos cómo importar datos en Python desde varios formatos importantes. Cubriremos:
Archivos serializados (Pickle): Usados para almacenar datos de manera eficiente en
Python. El concepto de serializados (Pickle) un archivo está motivado por lo siguiente: si bien puede ser fácil guardar una matriznumpyo undataframedepandasen un archivo plano, hay muchos otros tipos de datos, como diccionarios y listas, para los cuales no es obvio cómo almacenarlos.Hojas de Cálculo Excel: Permiten integrar datos de análisis de hojas de cálculo comunes.
Archivos SAS y Stata: Formatoss utilizados en software de estadística y análisis de datos.
Aprenderás a manejar estos formatos para que puedas trabajar con una amplia gama de datos en tus proyectos de ciencia de datos.
Importación y exportación de datos serializados#
Los datos serializados es el proceso de convertir los datos que han sido convertidos de su formato original (por ejemplo, un diccionario, una lista, un objeto de clase, etc.) a una secuencia de bytes. Este proceso se llama serialización o marshalling. La serialización permite que estos datos se almacenen en un archivo, se envíen a través de una red o se transmitan entre diferentes partes de un programa de manera eficiente. En Python, la serialización es manejada por el módulo pickle.
¿Por qué serializar datos?
Almacenamiento : Puedes guardar un objeto complejo (como un diccionario o un árbol binario) en un archivo y cargarlo más tarde sin perder su estructura.
Comunicación entre procesos: Los datos serializados pueden enviarse entre diferentes procesos de un programa o entre programas diferentes (por ejemplo, entre un cliente y un servidor en una aplicación web).
Persistencia de objetos: Los datos serializados permiten almacenar el estado de un objeto, de modo que pueda ser restaurado más tarde y seguir funcionando donde se dejó.
Por ejemplo
# Ejemplo
Ahora, exportemos los datos a un archivo .pkl usando pickle en Python, que es útil para serializar objetos de Python (como listas, diccionarios, o DataFrames). Aquí te muestro cómo hacerlo:
# Crear un objeto (por ejemplo, un diccionario)
data = {'a': 1, 'b': 2, 'c': 3}
# Guardar el objeto en un archivo pickle
# Ejemplo
Consideraciones
1 No cargues archivos pickle de fuentes no confiables, ya que pueden ejecutar código malicioso durante la deserialización.
Archivos
pickleson específicos dePython, por lo que no se pueden leer fácilmente en otros lenguajes de programación sin soporte parapickle.
Ejercicios
Complete el código:
# Importar el paquete pickle
# TU CÓDIGO
# Abre el archivo pickle y carga los datos llamados data: d
# TU CÓDIGO
# Imprime y el tipo de dato de d
# TU CÓDIGO
Importación y exportación de datos en Excel#
Las hojas de cálculo de Excel son una herramienta universalmente conocida y ampliamente utilizada, especialmente en el ámbito del análisis de datos. Un archivo de Excel generalmente contiene múltiples hojas de cálculo, cada una de las cuales puede almacenar diferentes conjuntos de datos relacionados o independientes. En el contexto de la ciencia de datos, el manejo eficiente de estos archivos es fundamental, y la biblioteca pandas de Python se destaca como una herramienta poderosa para este propósito.
Pandas permite importar archivos de Excel de manera sencilla y convertir sus hojas de cálculo en DataFrames, que son estructuras de datos optimizadas para el análisis y la manipulación de datos. La conversión de las hojas de Excel a DataFrames facilita enormemente el trabajo con los datos, ya que pandas proporciona una amplia gama de funciones para exploración, transformación y análisis.
Para comenzar, se puede utilizar la función ExcelFile de pandas para cargar un archivo de Excel en una variable, generalmente llamada data o algún nombre descriptivo. Este objeto ExcelFile actúa como un contenedor del archivo de Excel, permitiendo el acceso a sus diferentes hojas sin necesidad de cargarlas todas en la memoria al mismo tiempo.
# Ejemplo
Esto indica que el archivo contiene tres hojas de cálculo, cada una correspondiente a un rango de años diferente.
Una vez que conoces los nombres de las hojas, puedes cargar cualquier hoja en particular como un DataFrame para empezar a analizar los datos. Para hacer esto, utilizas el método parse del objeto ExcelFile. Este método acepta un argumento, que puede ser el nombre de la hoja como una cadena o su índice como un número entero (no como un float, ya que Python no acepta índices de hojas en forma de floats).
# Ejemplo
pandas es lo suficientemente inteligente para interpretar si le estás proporcionando un nombre de hoja o un índice, por lo que puedes utilizar cualquiera de los dos métodos según tu preferencia.
El método read_excel() de pandas es una función muy útil y versátil para leer archivos de Excel directamente en un DataFrame. A diferencia de ExcelFile y parse(), que se usan en conjunto cuando necesitas trabajar con múltiples hojas de un archivo de Excel, read_excel() es una función de uso directo que simplifica la lectura de una o más hojas de cálculo.
¿Cuándo usar read_excel()?
Lectura directa de una hoja de Excel: Si solo necesitas cargar una hoja específica de un archivo Excel sin necesidad de explorar todas las hojas primero,
read_excel()es la mejor opción.Lectura de múltiples hojas: Puedes leer varias hojas al mismo tiempo especificando una lista de nombres o índices de hojas.
Simplicidad:
read_excel()es más directa y menos verbosa que el uso combinado deExcelFileyparse().
Algunos ejemplos del uso de la función read_excel()
Leer una sola hoja de cálculo: Si sabes el nombre de la hoja que necesitas, puedes leerla directamente en un DataFrame:
# Lee la hoja '1960–1966' del archivo Excel y la carga en un DataFrame
# Ejemplo
O si prefieres usar el índice de la hoja:
# Ejemplo
Leer múltiples hojas al mismo tiempo: Si necesitas cargar varias hojas de un archivo de Excel,
read_excel()puede hacerlo en una sola llamada y devolver un diccionario donde las llaves son los nombres de las hojas y los valores son los DataFrames correspondientes.
# Ejemplo
Leer todas las hojas de un archivo de Excel: Si quieres leer todas las hojas del archivo de Excel sin tener que especificar sus nombres, puedes hacerlo pasando
Noneal argumentosheet_name.
# Lee todas las hojas del archivo Excel
# Ejemplo
read_excel() es ideal para situaciones en las que necesitas una solución rápida y directa para leer archivos de Excel en Python. Su simplicidad lo hace la primera opción para la mayoría de los casos de uso, mientras que ExcelFile y parse() ofrecen más flexibilidad para tareas más complejas.
Ahora, para exportar datos a un archivo Excel usando pandas, puedes utilizar el método to_excel() del DataFrame. Aquí te muestro cómo hacerlo, con opciones para personalizar la exportación. Por ejemplo
# Crear un DataFrame
data = {
'Columna1': [1, 4, 7],
'Columna2': [2, 5, 8],
'Columna3': [3, 6, 9]
}
df = pd.DataFrame(data)
# Guardar el DataFrame en un archivo Excel
# Ejemplo
Si quieres exportar a múltiples hojas de un archivo excel, puedes guardar diferentes DataFrames en diferentes hojas del mismo archivo Excel usando un ExcelWriter:
with pd.ExcelWriter('_data/datamanip/archivo_multihojas.xlsx') as writer:
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df2 = pd.DataFrame({'X': [5, 6], 'Y': [7, 8]})
# Guardar DataFrames en hojas diferentes
df1.to_excel(writer, sheet_name='Hoja1', index=False)
df2.to_excel(writer, sheet_name='Hoja2', index=False)
Ejercicios
Complete el código:
# Asigna el nombre del archivo de excel battledeath: file
# TU CÓDIGO
# Cargar hoja de cálculo: xls
# TU CÓDIGO
# Imprimir nombres de hojas
# TU CÓDIGO
Usando el punto anterior: Complete
# Cargar una hoja en un DataFrame por nombre: df1
df1 = xls.parse(__TU CÓDIGO__)
# Imprimir las primeras filas del DataFrame df1
print(__TU CÓDIGO__)
# Cargar una hoja en un DataFrame por índice: df2
df2 = xls.parse(__TU CÓDIGO__)
# Imprimir las primeras filas del DataFrame df2
print(__TU CÓDIGO__)
Usando el punto anterior. Complete en código en python. Sugerencia: Los valores pasados a
skiprowsy names deben ser todos del tipolist
# Analizar la primera hoja y renombrar las columnas: df1
df1 = xls.parse(__TU CÓDIGO__, skiprows=__TU CÓDIGO__, names=__TU CÓDIGO__)
# Imprimir las primeras filas del DataFrame df1
print(df1.head())
# Analizar la primera columna de la segunda hoja y renombrar la columna: df2
df2 = xls.parse(__TU CÓDIGO__, usecols=__TU CÓDIGO__, skiprows=__TU CÓDIGO__, names=__TU CÓDIGO__)
# Imprimir las primeras filas del DataFrame df2
print(df2.head())
Importación de ficheros planos desde la web#
Ahora puedes importar datos en Python desde todo tipo de archivos planos como .txt, .csv, otros tipos de archivos como archivos pickled, hojas de cálculo de Excel y archivos SAS y Stata. También has adquirido una valiosa experiencia en la consulta de bases de datos relacionales para importar datos de ellas mediante SQL. Sin embargo, todas estas habilidades implican la importación de datos de archivos que tiene localmente. Sin embargo, estas habilidades usualmente implican trabajar con archivos locales. En muchos casos, como científico de datos, necesitarás importar datos directamente desde la web.
Por ejemplo, supongamos que necesitas obtener el conjunto de datos de unas campañas de marketing directo (llamadas telefónicas) de una institución bancaria portuguesa desde el repositorio de GitHub de cdeoroaguado. Aunque puedes hacerlo manualmente usando un navegador, este método no es reproducible ni escalable. Es más eficiente y profesional utilizar código Python para automatizar la descarga e importación de estos datos.
Para hacer el proceso de importación desde la Web debemos tener algunos conceptos claros.
El paquete urllib en Python proporciona una interfaz de alto nivel para obtener datos de la World Wide Web. En particular, la función urlopen es similar a la función integrada open, pero acepta URLs en lugar de nombres de archivo.
Características de urllib
urllib tiene algunas funciones inmersas. Algunas son:
urlopen: Abre una URL y devuelve un objeto similar a un archivo.
urlretrieve: Descarga archivos directamente desde una URL y los guarda localmente.
Observación
Es útil para tareas sencillas de importación de datos desde la web.
Para tareas más complejas, podrías considerar el uso de
requestsjunto conBeautifulSoup.
# Ejemplo
Tambíen, podias hacer la lectura de los datos, sin descargalos. Por ejemplo
# Ejemplo
Manipulación de datos con pandas#
La librería pandas (cuyo nombre deriva de panel data, un término utilizado para describir conjuntos de datos estructurados y multidimensionales) ofrece potentes estructuras de datos y funciones de alto nivel que facilitan el trabajo con datos estructurados de manera eficiente y cómoda. Es una herramienta esencial en el análisis de datos, ampliamente utilizada por su versatilidad y funcionalidad.
Entre los principales objetos que proporciona pandas se encuentran el DataFrame, una estructura tabular bidimensional, la Serie, ambos construidos sobre arrays multidimensionales de NumPy y el Panel, que representa un cubo de datos tridimensional. Aunque NumPy es excelente para el almacenamiento eficiente de datos con su estructura `ndarray, presenta ciertas limitaciones en análisis más complejos. Estas limitaciones incluyen la falta de flexibilidad para aplicar etiquetas a los datos, gestionar valores faltantes, realizar agrupaciones, entre otros. Pandas supera estas barreras con sus estructuras de datos avanzadas, proporcionando una mayor flexibilidad y funcionalidad.
Para más información, puedes consultar la documentación oficial de pandas, donde encontrarás recursos y ejemplos detallados para aprovechar al máximo esta poderosa librería.
Recordemos algunas cosas de pandas
Para iniciar el proceso de creación, manipulación, entre otras debemos instalar el ia en el terminal. Recuerde activar el ambiente.

Importemos la libreria numpy y pandas
import pandas as pd
import numpy as np
Ahora, daremos los conceptos y ejemplos de una series.
Series#
Las series son estructuras similares a los arrays unidimensionales que ya hemos visto, con la diferencia de que también son homogéneas. Esto significa que todos sus elementos deben ser del mismo tipo y que su tamaño es fijo, es decir, no se puede modificar una vez definido.
Vamos a comenzar creando una serie a partir de una lista. Primero, necesitamos definir una lista con algunos datos. Por ejemplo:
# Definimos una lista de trabajos
trabajos = ["Ingeniero de Software", "Analista de Datos",
"Diseñador UX", "Gerente de Producto",
"Científico de datos"]
# Creamos un índice personalizado para estos trabajos
indices = ["Empresa1", "Empresa2", "Empresa3",
"Empresa4","Empresa5"]
Para crear la serie en Pandas usando estos datos y con indices personalizados, utilizamos el siguiente código:
serie = pd.Series(data = trabajos,dtype='string')
print(serie)
serie = pd.Series(data = trabajos,index=indices, dtype='string')
print(serie)
0 Ingeniero de Software
1 Analista de Datos
2 Diseñador UX
3 Gerente de Producto
4 Científico de datos
dtype: string
Empresa1 Ingeniero de Software
Empresa2 Analista de Datos
Empresa3 Diseñador UX
Empresa4 Gerente de Producto
Empresa5 Científico de datos
dtype: string
Ahora, vamos a crear una serie a partir de un diccionario
# Definimos un diccionario con trabajos y sus respectivos salarios
diccionario = {
"Ingeniero de Software": 70000,
"Analista de Datos": 60000,
"Diseñador UX": 65000,
"Gerente de Producto": 80000,
"Científico de datos": 65000
}
# Creamos una serie a partir del diccionario
serie_diccionario = pd.Series(diccionario)
print(serie_diccionario)
Ingeniero de Software 70000
Analista de Datos 60000
Diseñador UX 65000
Gerente de Producto 80000
Científico de datos 65000
dtype: int64
Para explorar algunos atributos de la serie, puedes usar los siguientes métodos:
# Tamaño de nuestra serie
serie_diccionario.size
# imprimir la lista de los nombres de las filas
serie_diccionario.index
# imprimir el tipo de datos
serie_diccionario.dtype
dtype('int64')
Para acceder a los elementos de la serie
# Accedemos a un elemento específico usando su índice
serie_diccionario['Ingeniero de Software']
# Accedemos a un rango de valores
serie_diccionario[0:3]
# Accedemos a múltiples elementos usando una lista de índices
serie_diccionario[['Ingeniero de Software','Analista de Datos']]
Ingeniero de Software 70000
Analista de Datos 60000
dtype: int64
serie_diccionario['Profesor'] = 100000
serie_diccionario
Ingeniero de Software 70000
Analista de Datos 60000
Diseñador UX 65000
Gerente de Producto 80000
Científico de datos 65000
Profesor 100000
dtype: int64
También puedes utilizar algunos métodos útiles para análisis, como:
# Usamos métodos para obtener estadísticas de la serie
print(serie_diccionario.count())
print(serie_diccionario.sum())
print(serie_diccionario.cumsum())
print(serie_diccionario.value_counts())
print(serie_diccionario.min())
print(serie_diccionario.max())
print(serie_diccionario.mean())
print(serie_diccionario.std())
print(serie_diccionario.quantile(0.25))
print(serie_diccionario.quantile(0.5))
print(serie_diccionario.quantile(0.75))
print(serie_diccionario.describe())
6
440000
Ingeniero de Software 70000
Analista de Datos 130000
Diseñador UX 195000
Gerente de Producto 275000
Científico de datos 340000
Profesor 440000
dtype: int64
65000 2
70000 1
60000 1
80000 1
100000 1
Name: count, dtype: int64
60000
100000
73333.33333333333
14719.601443879745
65000.0
67500.0
77500.0
count 6.000000
mean 73333.333333
std 14719.601444
min 60000.000000
25% 65000.000000
50% 67500.000000
75% 77500.000000
max 100000.000000
dtype: float64
Exploraremos cómo aplicar operaciones matemáticas y funciones a series de datos relacionadas con bancos, así como buscar información mediante condiciones, ordenar series y eliminar datos nulos o desconocidos.
Operaciones Matemáticas Básicas
Primero, veremos cómo aplicar operaciones matemáticas a una serie que representa los saldos de las cuentas bancarias. A continuación, presentamos algunos ejemplos prácticos:
# Una serie con saldos de cuentas bancarias
saldos = pd.Series([1500, 2000, 2500, 3000, 3500])
# Ejemplo
Filtrado de Datos
El objetivo es seleccionar saldos que cumplan una condición. Por ejemplo
# Seleccionar saldos mayores o iguales a 3000
# Ejemplo
# Seleccionar saldos diferentes a 3000
# Ejemplo
Ordenar series
Para ordenar los saldos de manera ascendente o descendente:
# Ejemplo
Eliminación de Datos Nulos y Desconocidos
Finalmente, para eliminar datos nulos o desconocidos en la serie de saldos:
# Crear valores nulos en la serie de saldos
saldos = pd.Series([1500, np.nan, 2500, None, 3500])
# Eliminar valores nulos
saldos_limpios = saldos.dropna()
print(saldos_limpios)
0 1500.0
2 2500.0
4 3500.0
dtype: float64
Con estos ejemplos, has aprendido cómo realizar diversas operaciones con series relacionadas con datos bancarios en Pandas. En la próximo sección, exploraremos cómo trabajar con DataFrames.
Pandas#
En este módulo, profundizaremos en la creación de DataFrames, una de las estructuras de datos más versátiles y poderosas para la manipulación de información financiera. Exploraremos tres métodos distintos para construir DataFrames, cada uno con aplicaciones específicas en la industria bancaria.
Un DataFrame es una estructura bidimensional, similar a una tabla, que nos permite organizar y manipular datos con facilidad. En el contexto bancario, los DataFrames son ideales para manejar información de clientes, transacciones, productos financieros, y otros tipos de datos críticos.
Método 1: Creación de DataFrames a partir de Diccionarios#
En este primer enfoque, utilizaremos un diccionario para organizar los datos de clientes bancarios. Las claves del diccionario representarán las columnas del DataFrame, tales como Nombre, Edad, Saldo, y Calificación_Crédito.
# Importación de la librería pandas
import pandas as pd
# Definición de los datos mediante un diccionario
clientes = {
'Nombre': ['José', 'Rodolfo', 'María', 'Julieta'],
'Edad': [45, 52, 34, 29],
'Saldo': [50000, 70000, 60000, 15000],
'Calificación_Crédito': [700, 750, 680, 720]
}
# Creación del DataFrame utilizando el diccionario
df_clientes = pd.DataFrame(clientes)
# Visualización del DataFrame
print(df_clientes)
Este enfoque es eficiente cuando se tiene un conjunto de datos bien estructurado, con columnas predefinidas y valores coherentes. Es comúnmente utilizado en situaciones donde los datos provienen de sistemas bancarios estructurados, como bases de datos relacionales.
Método 2: Creación de DataFrames a partir de Listas Anidadas#
El siguiente método consiste en utilizar listas de listas para estructurar los datos. Este enfoque puede ser útil cuando los datos provienen de una fuente menos estructurada, como archivos CSV o entrada manual.
# Definición de los datos mediante listas anidadas
datos_clientes = [
['José', 45, 50000, 700],
['Rodolfo', 52, 70000, 750],
['María', 34, 60000, 680],
['Julieta', 29, 15000, 720]
]
# Definición de las columnas
columnas = ['Nombre', 'Edad', 'Saldo', 'Calificación_Crédito']
# Creación del DataFrame
df_clientes_lista = pd.DataFrame(datos_clientes, columns=columnas)
# Visualización del DataFrame
print(df_clientes_lista)
Este método es particularmente útil cuando los datos no están previamente etiquetados y requieren un procesamiento adicional para ser organizados en un formato tabular. Es frecuente en la integración de datos desde múltiples fuentes no homogéneas, como encuestas o registros de transacciones.
Método 3: Creación de DataFrames a partir de Listas de Diccionarios#
Finalmente, exploraremos cómo crear un DataFrame a partir de una lista de diccionarios. Este método es flexible y permite manejar datos con campos opcionales o información incompleta, algo común en grandes bases de datos bancarias.
# Definición de los datos mediante una lista de diccionarios
clientes_dict = [
{'Nombre': 'José', 'Edad': 45, 'Saldo': 50000, 'Calificación_Crédito': 700},
{'Nombre': 'Rodolfo', 'Edad': 52, 'Saldo': 70000, 'Calificación_Crédito': 750},
{'Nombre': 'María', 'Edad': 34, 'Saldo': 60000}, # Falta calificación de crédito
{'Nombre': 'Julieta', 'Edad': 29, 'Calificación_Crédito': 720}, # Falta saldo
{'Edad': 28, 'Saldo': 30000} # Faltan nombre y calificación de crédito
]
# Creación del DataFrame
df_clientes_dict = pd.DataFrame(clientes_dict)
# Visualización del DataFrame
print(df_clientes_dict)
La capacidad de manejar datos incompletos o parcialmente definidos es crucial en el análisis de datos bancarios, donde la información puede provenir de fuentes dispares y no siempre estará completa. Este método permite construir DataFrames robustos que pueden ser limpiados o completados en etapas posteriores del análisis.
Observación
Algunas diferencias clave entre una Serie (Series) y un DataFrame en Pandas:
Dimensionalidad:
Serie: Es unidimensional, como una lista o columna única de datos.
DataFrame: Es bidimensional, similar a una tabla con múltiples filas y columnas.
Estructura:
Serie: Contiene una sola columna de datos con un índice.
DataFrame: Contiene múltiples columnas, cada una de las cuales es una Serie.
Uso:
Serie: Ideal para manejar una sola secuencia de datos.
DataFrame: Ideal para trabajar con datos tabulares que tienen múltiples variables o características.
Etiquetas del Eje:
Serie: Tiene un único conjunto de etiquetas o índice asociado con los datos.
DataFrame: Tiene dos ejes de etiquetas: uno para las filas (índice) y otro para las columnas.
Operaciones de Agregación:
Serie: Las operaciones de agregación, como la suma o el promedio, se aplican directamente a la secuencia de datos.
DataFrame: Puedes aplicar operaciones de agregación a lo largo de filas o columnas, permitiendo un análisis más detallado y comparativo.
Manipulación#
La manipulación de datos con Pandas es una de las habilidades fundamentales en el análisis de datos. Pandas es una biblioteca de Python que proporciona estructuras de datos fáciles de usar, como Series y DataFrames, que permiten realizar operaciones y transformaciones complejas de manera sencilla y eficiente.
Introducción a la manipulación de datos#
Ahora carguemos el conjunto de datos de marketing del banco bank-full.
Los datos están relacionados con campañas de marketing directo (llamadas telefónicas) de una institución bancaria portuguesa.
Este conjunto de datos tiene 4521 observaciones y 17 variables. Las variables son:
age: Edad del cliente.
job: Profesión del cliente (por ejemplo, desempleado, servicios, gestión).
marital: Estado civil del cliente (soltero, casado, divorciado).
education: Nivel educativo del cliente (primaria, secundaria, terciaria).
default : Indica si el cliente tiene crédito en incumplimiento (sí o no).
balance: Saldo promedio anual de la cuenta bancaria del cliente.
housing: Indica si el cliente tiene un préstamo hipotecario (sí o no).
loan: Indica si el cliente tiene un préstamo personal (sí o no).
contact: Tipo de comunicación de contacto (teléfono celular, teléfono fijo).
day: Día del mes en que se realizó el último contacto con el cliente.
month: Mes en que se realizó el último contacto con el cliente.
duration: Duración del último contacto en segundos.
campaign: Número de contactos realizados durante esta campaña de marketing.
pdays: Días que han pasado desde que el cliente fue contactado por última vez en una campaña anterior (valores -1 indican que el cliente no fue contactado previamente).
previous: Número de contactos realizados antes de esta campaña.
poutcome: Resultado de una campaña de marketing anterior (éxito, fracaso, desconocido).
y: Resultado de la campaña actual (si el cliente suscribió o no un depósito a plazo fijo).
import pandas as pd
filename = 'C:/GitHub/Datos/datamanip/bank/bank-full.csv'
data = pd.read_csv(filename,sep=';')
data.head()
| age | job | marital | education | default | balance | housing | loan | contact | day | month | duration | campaign | pdays | previous | poutcome | y | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 58 | management | married | tertiary | no | 2143 | yes | no | unknown | 5 | may | 261 | 1 | -1 | 0 | unknown | no |
| 1 | 44 | technician | single | secondary | no | 29 | yes | no | unknown | 5 | may | 151 | 1 | -1 | 0 | unknown | no |
| 2 | 33 | entrepreneur | married | secondary | no | 2 | yes | yes | unknown | 5 | may | 76 | 1 | -1 | 0 | unknown | no |
| 3 | 47 | blue-collar | married | unknown | no | 1506 | yes | no | unknown | 5 | may | 92 | 1 | -1 | 0 | unknown | no |
| 4 | 33 | unknown | single | unknown | no | 1 | no | no | unknown | 5 | may | 198 | 1 | -1 | 0 | unknown | no |
url = 'https://raw.githubusercontent.com/cdeoroaguado/Datos/refs/heads/main/datamanip/bank/bank-full.csv'
df = pd.read_csv(url,sep=';')
df.head()
| age | job | marital | education | default | balance | housing | loan | contact | day | month | duration | campaign | pdays | previous | poutcome | y | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 58 | management | married | tertiary | no | 2143 | yes | no | unknown | 5 | may | 261 | 1 | -1 | 0 | unknown | no |
| 1 | 44 | technician | single | secondary | no | 29 | yes | no | unknown | 5 | may | 151 | 1 | -1 | 0 | unknown | no |
| 2 | 33 | entrepreneur | married | secondary | no | 2 | yes | yes | unknown | 5 | may | 76 | 1 | -1 | 0 | unknown | no |
| 3 | 47 | blue-collar | married | unknown | no | 1506 | yes | no | unknown | 5 | may | 92 | 1 | -1 | 0 | unknown | no |
| 4 | 33 | unknown | single | unknown | no | 1 | no | no | unknown | 5 | may | 198 | 1 | -1 | 0 | unknown | no |
df. tail()
# concatenar
result = pd.concat([df.head(),df.tail()],ignore_index=True)
result
| age | job | marital | education | default | balance | housing | loan | contact | day | month | duration | campaign | pdays | previous | poutcome | y | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 58 | management | married | tertiary | no | 2143 | yes | no | unknown | 5 | may | 261 | 1 | -1 | 0 | unknown | no |
| 1 | 44 | technician | single | secondary | no | 29 | yes | no | unknown | 5 | may | 151 | 1 | -1 | 0 | unknown | no |
| 2 | 33 | entrepreneur | married | secondary | no | 2 | yes | yes | unknown | 5 | may | 76 | 1 | -1 | 0 | unknown | no |
| 3 | 47 | blue-collar | married | unknown | no | 1506 | yes | no | unknown | 5 | may | 92 | 1 | -1 | 0 | unknown | no |
| 4 | 33 | unknown | single | unknown | no | 1 | no | no | unknown | 5 | may | 198 | 1 | -1 | 0 | unknown | no |
| 5 | 51 | technician | married | tertiary | no | 825 | no | no | cellular | 17 | nov | 977 | 3 | -1 | 0 | unknown | yes |
| 6 | 71 | retired | divorced | primary | no | 1729 | no | no | cellular | 17 | nov | 456 | 2 | -1 | 0 | unknown | yes |
| 7 | 72 | retired | married | secondary | no | 5715 | no | no | cellular | 17 | nov | 1127 | 5 | 184 | 3 | success | yes |
| 8 | 57 | blue-collar | married | secondary | no | 668 | no | no | telephone | 17 | nov | 508 | 4 | -1 | 0 | unknown | no |
| 9 | 37 | entrepreneur | married | secondary | no | 2971 | no | no | cellular | 17 | nov | 361 | 2 | 188 | 11 | other | no |
Las dimensiones del dataset:
df.shape
(45211, 17)
Información de la estructura del dataset de marketing:
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 45211 entries, 0 to 45210
Data columns (total 17 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 age 45211 non-null int64
1 job 45211 non-null object
2 marital 45211 non-null object
3 education 45211 non-null object
4 default 45211 non-null object
5 balance 45211 non-null int64
6 housing 45211 non-null object
7 loan 45211 non-null object
8 contact 45211 non-null object
9 day 45211 non-null int64
10 month 45211 non-null object
11 duration 45211 non-null int64
12 campaign 45211 non-null int64
13 pdays 45211 non-null int64
14 previous 45211 non-null int64
15 poutcome 45211 non-null object
16 y 45211 non-null object
dtypes: int64(7), object(10)
memory usage: 5.9+ MB
El atributo df.size en pandas devuelve el número total de elementos en un DataFrame. Esto se calcula multiplicando el número de filas por el número de columnas. Es útil para obtener una visión rápida del tamaño total del DataFrame en términos de elementos.
# número total de elementos en el dataframe
df.size
768587
Puede ocurrir que el conjunto de datos de marketing para la banca tenga duplicados. El método drop_duplicates() en pandas se utiliza para eliminar filas duplicadas de un DataFrame. Este método permite identificar y remover filas que contienen los mismos valores en las columnas seleccionadas, o en todas las columnas si no se especifica ninguna.
# Eliminar filas duplicadas
df = df.drop_duplicates()
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 45211 entries, 0 to 45210
Data columns (total 17 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 age 45211 non-null int64
1 job 45211 non-null object
2 marital 45211 non-null object
3 education 45211 non-null object
4 default 45211 non-null object
5 balance 45211 non-null int64
6 housing 45211 non-null object
7 loan 45211 non-null object
8 contact 45211 non-null object
9 day 45211 non-null int64
10 month 45211 non-null object
11 duration 45211 non-null int64
12 campaign 45211 non-null int64
13 pdays 45211 non-null int64
14 previous 45211 non-null int64
15 poutcome 45211 non-null object
16 y 45211 non-null object
dtypes: int64(7), object(10)
memory usage: 5.9+ MB
df_sin_nulos = df.dropna()
df_sin_nulos.info()
Ahora, el nombres de las variables, el indice, el tipo de dato del dataset de marketing
# nombre de las variables
df.columns
# Obtener el índice del DataFrame
df.index
# tipo de dato
df.dtypes
age int64
job object
marital object
education object
default object
balance int64
housing object
loan object
contact object
day int64
month object
duration int64
campaign int64
pdays int64
previous int64
poutcome object
y object
dtype: object
Queremos saber los clientes menores de 20 años:
# Seleccionar solo las filas donde la condición es True
# df['age'] < 20
df.loc[:,'age'] < 20
# Mostrar los clientes menores de 20 años
dfm20 = df[df.loc[:,'age'] < 20]
# imprimir el dataframe las 5 primeras
dfm20.head()
| age | job | marital | education | default | balance | housing | loan | contact | day | month | duration | campaign | pdays | previous | poutcome | y | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 30791 | 19 | student | single | unknown | no | 1169 | no | no | cellular | 6 | feb | 463 | 18 | -1 | 0 | unknown | no |
| 31041 | 19 | student | single | unknown | no | 0 | no | no | cellular | 11 | feb | 123 | 3 | -1 | 0 | unknown | no |
| 31263 | 19 | student | single | unknown | no | 27 | no | no | telephone | 5 | mar | 86 | 12 | -1 | 0 | unknown | no |
| 31304 | 19 | student | single | secondary | no | 1803 | no | no | cellular | 10 | mar | 59 | 1 | -1 | 0 | unknown | no |
| 31432 | 19 | student | single | primary | no | 134 | no | no | cellular | 27 | mar | 271 | 2 | -1 | 0 | unknown | yes |
Escojamos las columnas age, marital, balance, y de los clientes menores de 20
new_dfm20 = dfm20[['age','marital','balance','y']]
new_dfm20.head()
| age | marital | balance | y | |
|---|---|---|---|---|
| 30791 | 19 | single | 1169 | no |
| 31041 | 19 | single | 0 | no |
| 31263 | 19 | single | 27 | no |
| 31304 | 19 | single | 1803 | no |
| 31432 | 19 | single | 134 | yes |
new_dfm20.to_csv('C:/Users/cdeor/OneDrive/Escritorio/archivo.csv',sep = ';',index =False)
Para saber quien tiene mayor balance en la cuenta de los menores de 20, debo ordenarlo usando el método sort_values:
# ordenar
new_dfm20.sort_values(by='balance', ascending=False)
| age | marital | balance | y | |
|---|---|---|---|---|
| 34281 | 19 | single | 5368 | no |
| 40736 | 18 | single | 1944 | no |
| 40376 | 19 | single | 1803 | no |
| 31304 | 19 | single | 1803 | no |
| 33774 | 19 | single | 1247 | no |
| 30791 | 19 | single | 1169 | no |
| 31492 | 19 | single | 779 | yes |
| 32169 | 19 | single | 626 | no |
| 43680 | 19 | single | 608 | yes |
| 42274 | 18 | single | 608 | yes |
| 40887 | 18 | single | 608 | yes |
| 41446 | 19 | single | 527 | no |
| 42488 | 19 | single | 526 | no |
| 44058 | 19 | single | 526 | no |
| 44644 | 18 | single | 438 | no |
| 44042 | 19 | single | 424 | no |
| 43408 | 19 | single | 394 | yes |
| 44110 | 19 | single | 372 | yes |
| 43637 | 18 | single | 348 | yes |
| 41930 | 19 | single | 329 | yes |
| 43594 | 19 | single | 329 | yes |
| 44211 | 19 | single | 302 | yes |
| 34675 | 19 | single | 291 | no |
| 45170 | 19 | single | 245 | no |
| 41619 | 19 | single | 179 | no |
| 42146 | 18 | single | 156 | no |
| 31432 | 19 | single | 134 | yes |
| 44493 | 19 | single | 108 | yes |
| 40744 | 18 | single | 108 | yes |
| 41487 | 18 | single | 108 | yes |
| 42954 | 18 | single | 108 | yes |
| 43258 | 19 | single | 108 | yes |
| 42705 | 19 | single | 103 | no |
| 40564 | 19 | single | 103 | yes |
| 41830 | 19 | single | 103 | no |
| 33789 | 19 | single | 96 | no |
| 41500 | 19 | single | 88 | no |
| 41057 | 19 | single | 60 | no |
| 40927 | 19 | single | 56 | no |
| 41706 | 19 | single | 55 | no |
| 41222 | 18 | single | 35 | no |
| 31263 | 19 | single | 27 | no |
| 41252 | 18 | single | 5 | no |
| 41402 | 19 | single | 4 | no |
| 41273 | 18 | single | 3 | yes |
| 34288 | 19 | single | 0 | no |
| 31041 | 19 | single | 0 | no |
Puedes aplicar una función personalizada a una columna específica del DataFrame usando el método apply() de pandas. Supongamos que deseas crear una nueva columna llamada balance_category que clasifique el balance de cada cliente en "Bajo", "Medio" o "Alto" según ciertos umbrales.
def categorizar_balance(balance):
if balance < 500:
return 'Bajo'
elif 500 <= balance < 1500:
return 'Medio'
else:
return 'Alto'
# new_dfm20['balance_category'] = new_dfm20['balance'].apply(categorizar_balance)
new_dfm20.loc[:,'balance_category'] = new_dfm20['balance'].apply(categorizar_balance)
new_dfm20.head()
| age | marital | balance | y | balance_category | |
|---|---|---|---|---|---|
| 30791 | 19 | single | 1169 | no | Medio |
| 31041 | 19 | single | 0 | no | Bajo |
| 31263 | 19 | single | 27 | no | Bajo |
| 31304 | 19 | single | 1803 | no | Alto |
| 31432 | 19 | single | 134 | yes | Bajo |
Ahora, debemos obtener los clientes menores de 20 que si se suscribieron. Ademas los que se suscribieron con balance bajo.
# menores de 20 que se suscribieron
new_dfm20.loc[new_dfm20['y']=='yes']
# Otra forma de seleccionarlos
new_dfm20[new_dfm20['y'].isin(['yes'])]
# menores de 20 que se suscribieron con balance bajo
new_dfm20.loc[(new_dfm20['y']=='yes') & (new_dfm20['balance_category']=='Bajo')].head()
| age | marital | balance | y | balance_category | |
|---|---|---|---|---|---|
| 31432 | 19 | single | 134 | yes | Bajo |
| 40564 | 19 | single | 103 | yes | Bajo |
| 40744 | 18 | single | 108 | yes | Bajo |
| 41273 | 18 | single | 3 | yes | Bajo |
| 41487 | 18 | single | 108 | yes | Bajo |
Adición de nuevas columnas al DataFrame#
En este ejercicio, vamos a añadir nuevas columnas al conjunto de datos de diamantes en la biblioteca pandas. Empezaremos con la adición simple de columnas y luego avanzaremos y veremos la adición condicional de columnas. Para ello, vamos a seguir los siguientes pasos:
Anade una columna
balance_por_agealDataFrame. Del mismo modo, también podemos utilizar la suma, la resta y otros operadores matemáticos sobre dos columnas numéricas.
# Ejemplo
Ahora, veremos la adición condicional de columnas. Vamos a intentar añadir una columna basada en el valor de la edad, digamos que todo lo que sea más de 17 como mayor de edad (codificado como 1) y todo lo que sea inferior a 17 como menor de edad (codificado como 0).
# Ejemplo
Descripción estadística#
Exploraremos cómo obtener estadísticas de resumen detalladas para columnas específicas de un DataFrame, así como cómo realizar análisis estadísticos avanzados mediante agrupaciones y tablas dinámicas. Comenzaremos con el cálculo de métricas descriptivas básicas, tales como medias, medianas, y desviaciones estándar, para evaluar la distribución y variabilidad de los datos. A continuación, abordaremos técnicas para aplicar estas estadísticas a subconjuntos de datos mediante agrupaciones, permitiendo un análisis más granular y enfocado.
Finalmente, dominaremos el uso de tablas dinámicas para sintetizar, visualizar y resumir datos complejos, facilitando la extracción de insights clave y patrones significativos en grandes volúmenes de información. Este enfoque integral fortalecerá tu capacidad para extraer, interpretar y comunicar hallazgos estadísticos de manera efectiva en el análisis de datos.
Resumen estadístico univariado#
Calculemos las medidas descriptivas fundamentales, incluyendo la media, mediana, moda, varianza, desviación estándar y cuartiles, para proporcionar una visión general de la distribución de los datos. Usaremos el conjunto de datos.
Si la variable es numérica
df['age'].mean()
# Resumen descriptivo de una sola variable numérica
df['age'].agg({
'Promedio':'mean',
'Desv Estandar':'std',
'Minimo':'min',
'Maximo':'max',
'Mediana':'median',
'Q1': lambda x: x.quantile(0.25),
'Q3': lambda x: x.quantile(0.75)
})
Promedio 40.936210
Desv Estandar 10.618762
Minimo 18.000000
Maximo 95.000000
Mediana 39.000000
Q1 33.000000
Q3 48.000000
Name: age, dtype: float64
result = pd.DataFrame({
'Promedio':df[['age','balance']].mean(),
'Desv. Estandar':df[['age','balance']].std(),
'Minimo':df[['age','balance']].min(),
'Maximo':df[['age','balance']].max(),
'Mediana':df[['age','balance']].median(),
'Q1':df[['age','balance']].quantile(0.25),
'Q3':df[['age','balance']].quantile(0.75)
})
result
| Promedio | Desv. Estandar | Minimo | Maximo | Mediana | Q1 | Q3 | |
|---|---|---|---|---|---|---|---|
| age | 40.936210 | 10.618762 | 18 | 95 | 39.0 | 33.0 | 48.0 |
| balance | 1362.272058 | 3044.765829 | -8019 | 102127 | 448.0 | 72.0 | 1428.0 |
Si la variable es catégorica
conteo = df['job'].value_counts()
conteo
proporcion = df['job'].value_counts(normalize=True)
proporcion
porcentaje = df['job'].value_counts(normalize=True)*100
porcentaje
resultado = pd.DataFrame({
'Numero de clientes':conteo,
'Porcentaje':porcentaje
})
resultado
| Numero de clientes | Porcentaje | |
|---|---|---|
| job | ||
| blue-collar | 9732 | 21.525735 |
| management | 9458 | 20.919688 |
| technician | 7597 | 16.803433 |
| admin. | 5171 | 11.437482 |
| services | 4154 | 9.188029 |
| retired | 2264 | 5.007631 |
| self-employed | 1579 | 3.492513 |
| entrepreneur | 1487 | 3.289023 |
| unemployed | 1303 | 2.882042 |
| housemaid | 1240 | 2.742695 |
| student | 938 | 2.074716 |
| unknown | 288 | 0.637013 |
conteo = df[['job','education']].value_counts()
conteo
proporcion = df[['job','education']].value_counts(normalize=True)
proporcion
porcentaje = df[['job','education']].value_counts(normalize=True)*100
porcentaje
resultado = pd.DataFrame({
'Numero de clientes':conteo,
'Porcentaje':porcentaje
})
resultado
| Numero de clientes | Porcentaje | ||
|---|---|---|---|
| job | education | ||
| management | tertiary | 7801 | 17.254650 |
| blue-collar | secondary | 5371 | 11.879852 |
| technician | secondary | 5229 | 11.565769 |
| admin. | secondary | 4219 | 9.331800 |
| blue-collar | primary | 3758 | 8.312136 |
| services | secondary | 3457 | 7.646369 |
| technician | tertiary | 1968 | 4.352923 |
| management | secondary | 1121 | 2.479485 |
| retired | secondary | 984 | 2.176461 |
| self-employed | tertiary | 833 | 1.842472 |
| retired | primary | 795 | 1.758422 |
| unemployed | secondary | 728 | 1.610228 |
| entrepreneur | tertiary | 686 | 1.517330 |
| housemaid | primary | 627 | 1.386831 |
| self-employed | secondary | 577 | 1.276238 |
| admin. | tertiary | 572 | 1.265179 |
| entrepreneur | secondary | 542 | 1.198823 |
| student | secondary | 508 | 1.123620 |
| blue-collar | unknown | 454 | 1.004180 |
| housemaid | secondary | 395 | 0.873681 |
| retired | tertiary | 366 | 0.809538 |
| services | primary | 345 | 0.763089 |
| management | primary | 294 | 0.650284 |
| unemployed | tertiary | 289 | 0.639225 |
| primary | 257 | 0.568446 | |
| management | unknown | 242 | 0.535268 |
| technician | unknown | 242 | 0.535268 |
| student | tertiary | 223 | 0.493243 |
| admin. | primary | 209 | 0.462277 |
| services | tertiary | 202 | 0.446794 |
| entrepreneur | primary | 183 | 0.404769 |
| housemaid | tertiary | 173 | 0.382650 |
| admin. | unknown | 171 | 0.378227 |
| student | unknown | 163 | 0.360532 |
| technician | primary | 158 | 0.349472 |
| services | unknown | 150 | 0.331778 |
| blue-collar | tertiary | 149 | 0.329566 |
| self-employed | primary | 130 | 0.287541 |
| unknown | unknown | 127 | 0.280905 |
| retired | unknown | 119 | 0.263210 |
| entrepreneur | unknown | 76 | 0.168101 |
| unknown | secondary | 71 | 0.157041 |
| primary | 51 | 0.112804 | |
| housemaid | unknown | 45 | 0.099533 |
| student | primary | 44 | 0.097321 |
| self-employed | unknown | 39 | 0.086262 |
| unknown | tertiary | 39 | 0.086262 |
| unemployed | unknown | 29 | 0.064144 |
Resumen estadístico bivariado#
El resumen estadístico bivariado se refiere al estudio de dos variables simultáneamente para determinar si existe alguna relación o asociación entre ellas. Solo realizaremos las tablas para dicho análisis estadístico.
Variable categórica vs variable numérica
df.groupby('y')['age'].mean()
var_num_cat = df.groupby('y')['age'].agg([
('Promedio','mean'),
('Desv. Estandar','std'),
('Minimo','min'),
('Maximo','max'),
('Mediana','median'),
('Q1',lambda x: x.quantile(0.25)),
('Q3',lambda x: x.quantile(0.75))
])
var_num_cat
| Promedio | Desv. Estandar | Minimo | Maximo | Mediana | Q1 | Q3 | |
|---|---|---|---|---|---|---|---|
| y | |||||||
| no | 40.838986 | 10.172662 | 18 | 95 | 39.0 | 33.0 | 48.0 |
| yes | 41.670070 | 13.497781 | 18 | 95 | 38.0 | 31.0 | 50.0 |
Resumen estadístico con tablas dinámicas#
Las tablas dinámicas son otras formas de calcular estadística de resumen agrupada. Por ejemplo
# Ejemplo
Ahora, usemos pivot_table para dos variables categóricas. Por ejemplo
# Ejemplo
Para crear una tabla de contigencia, basta con tener dos variables categóricas. Por ejemplo
# Ejemplo
Indices explicitos#
En Python, los índices son utilizados para acceder a elementos en estructuras de datos como listas, tuplas, y matrices (arrays). Un índice explícito se refiere a la práctica de definir de manera específica el índice que se va a utilizar para acceder a un elemento, en lugar de depender de la indexación automática por la posición.
Características de los Índices Explícitos
Flexibilidad: Permiten el acceso a elementos específicos de una estructura de datos sin necesidad de recorrer secuencialmente todos los elementos.
Claridad: Facilitan la lectura y comprensión del código al hacer evidente qué elementos se están accediendo o modificando.
Manipulación de Datos: Hacen más sencillo realizar operaciones como reordenar elementos, filtrar,seleccionar, agrupar o acceder a subconjuntos de datos.
Compatibilidad con Pandas: En bibliotecas como pandas, los índices explícitos son fundamentales para trabajar con Series y DataFrames, permitiendo indexar tanto por números como por etiquetas.
Precisión: Al especificar el índice, reduces el riesgo de errores al manipular datos.
Eficiencia: Mejoran la eficiencia al permitir operaciones directas sobre los elementos deseados.
Visualicemos nuevamente el dataframe de marketing para la banca.
# marco de datos
df.head()
| age | job | marital | education | default | balance | housing | loan | contact | day | month | duration | campaign | pdays | previous | poutcome | y | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 58 | management | married | tertiary | no | 2143 | yes | no | unknown | 5 | may | 261 | 1 | -1 | 0 | unknown | no |
| 1 | 44 | technician | single | secondary | no | 29 | yes | no | unknown | 5 | may | 151 | 1 | -1 | 0 | unknown | no |
| 2 | 33 | entrepreneur | married | secondary | no | 2 | yes | yes | unknown | 5 | may | 76 | 1 | -1 | 0 | unknown | no |
| 3 | 47 | blue-collar | married | unknown | no | 1506 | yes | no | unknown | 5 | may | 92 | 1 | -1 | 0 | unknown | no |
| 4 | 33 | unknown | single | unknown | no | 1 | no | no | unknown | 5 | may | 198 | 1 | -1 | 0 | unknown | no |
Analicemos algunas funciones utiles de la indexación explicita:
df.set_index(); Este método se usa para establecer una o más columnas del DataFrame como su índice.
# Establecer la columna 'job' como índice
# Ejemplo
df.reset_index():Este método se usa para restablecer el índice del DataFrame, devolviendo los índices actuales a columnas y creando un nuevo índice numérico predeterminado. Si usas el parámetrodrop=Trueindica que se debe eliminar la columna de índice original en lugar de moverla a una columna.
# Ejemplo
df.sort_index(): Este método ordena las filas del DataFrame en función del índice.
import pandas as pd
from ydata_profiling import ProfileReport
filename = 'C:/GitHub/Datos/datamanip/bank/bank-full.csv'
df = pd.read_csv(filename,sep=';')
profile = ProfileReport(df,title='Informe de los datos', explorative = True)
profile.to_notebook_iframe()
profile.to_file('C:/Users/cdeor/OneDrive/Escritorio/Informe_datos.html')
En conclusión, el uso de índices explícitos en Python es una técnica poderosa que permite un control detallado sobre la manipulación de datos. Ya sea en estructuras simples como listas o en análisis más complejos utilizando pandas, el conocimiento y uso adecuado de índices explícitos puede mejorar significativamente la eficiencia y claridad de tu código.
Visualización sencilla de datos#
Para el desarrollo de las visualización trabajaremos con datos sobre los almacenes Walmart, que es un cadena de grande almacenes de Ewa.
El conjunto de datos completos lo puede encontrar este link. Trabajaremos un subconjunto de datos contiene las ventas semanales en dolares, cada tienda tiene un número de identificación y un tipo de tienda específico, las ventas estan separadas por ID de departamento. Junto con las ventas hay variables como si fue de vacaciones o no, la temperatura media durante la semana en esa localidad, el tiempo medio del combustible en dolares por litro esa semana y la tasa de desempleo de esa semana
Aquí tienes una explicación de las variables en el conjunto de datos de ventas proporcionado:
Unnamed: Columna de índice que parece haber sido incluida al guardar el archivo. No es una variable significativa.
store: Identificador del número de la tienda.
type: Tipo de tienda, representado por una letra (por ejemplo, “A”, “B”, etc.).
department: Identificador del número de departamento dentro de la tienda.
date: Fecha en la que se registró la venta.
weekly_sales: Ventas semanales en USD registradas en esa tienda y departamento específicos.
is_holiday: Variable booleana que indica si la fecha corresponde a un día festivo o no. Los valores son “True” o “False”.
temperature_c: Temperatura en grados Celsius en la fecha registrada.
fuel_price_usd_per_l: Precio del combustible en dólares estadounidenses por litro en la fecha registrada.
unemployment: Tasa de desempleo en la fecha registrada.
Carguemos el conjunto de datos:
# Ejemplo
# Renombrar una columna
# Ejemplo
# Ejemplo
Matplotlib es especialmente útil cuando necesitas crear gráficos personalizados y detallados, y es una herramienta esencial para cualquier persona que trabaje con visualización de datos en Python. Haremos unas gráficas univariadas
Histograma#
Un histograma es una representación gráfica que muestra la distribución de una variable continua. Se divide el rango de valores en intervalos (bins) y se cuenta cuántos valores caen en cada intervalo.
Características del histograma
Ideal para visualizar la forma de la distribución de los datos.
Ayuda a identificar la simetría, la dispersión, y la presencia de outliers.
El número de
binsafecta la interpretación; demasiados o muy pocosbinspueden ocultar patrones importantes.Permite una fácil visualización de la distribución de datos.
Útil para identificar la presencia de sesgos en los datos.
No es útil para datos categóricos.
# importar matplotlib
import matplotlib.pyplot as plt
# Histograma de las ventas semanales
# Ejemplo
# Otra forma
# Ejemplo
import warnings
warnings.filterwarnings("ignore")
# Ejemplo
# Ejemplo
Densidad#
Una gráfica de densidad es una representación gráfica suave de la distribución de una variable continua. Se basa en la estimación de la función de densidad de probabilidad (KDE, por sus siglas en inglés), lo que permite visualizar la forma general de la distribución sin depender de intervalos rígidos como en los histogramas.
Características de la gráfica de densidad
Ideal para visualizar la forma suave de la distribución de los datos.
Útil para comparar distribuciones entre varios grupos.
No requiere la definición de
bins, a diferencia del histograma.Permite identificar modas (picos), simetría, y presencia de sesgos.
Es sensible al parámetro de suavizado (
bandwidth), el cual afecta la forma de la curva.A diferencia del histograma, muestra una curva continua.
No es útil para datos categóricos.
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
# Estimación de densidad usando KDE
kde = gaussian_kde(df['fuel_price_usd_per_l'].dropna())
x_vals = np.linspace(min(data), max(data), 1000)
y_vals = kde(x_vals)
# Gráfico
plt.figure(figsize=(8, 4))
plt.plot(x_vals, y_vals, color='blue', lw=2, label='Densidad KDE')
plt.fill_between(x_vals, y_vals, alpha=0.3, color='blue')
plt.title('Gráfica de densidad de precio del combustible (Matplotlib + SciPy)')
plt.xlabel('Precio USD por litro')
plt.ylabel('Densidad')
plt.legend()
plt.grid(True)
plt.show()
Histograma con función de densidad#
Un histograma con función de densidad combina la representación clásica del histograma (que agrupa los datos en intervalos) con una curva de densidad suave (estimación KDE). Esta combinación permite visualizar tanto la frecuencia aproximada de los valores como la forma general de la distribución de los datos.
Características del histograma con función de densidad
Combina la vista detallada del histograma con la suavidad de la curva de densidad.
Útil para observar la frecuencia de los datos junto con la tendencia general.
Permite detectar sesgos, modas, simetría, y posibles valores atípicos.
El número de
binsinfluye en la forma del histograma; la curva de densidad ayuda a suavizar esa variabilidad.La curva KDE puede verse afectada por el parámetro de suavizado (
bandwidth).Ideal para explorar la distribución de variables continuas.
# KDE
kde = gaussian_kde(df['fuel_price_usd_per_l'].dropna())
x_vals = np.linspace(min(data), max(data), 1000)
y_vals = kde(x_vals)
# Gráfico
plt.figure(figsize=(8, 4))
plt.hist(data, bins=30, density=True, alpha=0.4, color='skyblue', label='Histograma')
plt.plot(x_vals, y_vals, color='darkblue', lw=2, label='Densidad KDE')
plt.title('Histograma con curva de densidad')
plt.xlabel('Precio USD por litro')
plt.ylabel('Densidad')
plt.legend()
plt.grid(True)
plt.show()
Una transformación logarítmica ayuda a identificar más tendencias. Por ejemplo, en el siguiente gráfico, el eje muestra los valores transformados en logaritmos de la variable del precio, y vemos que hay dos o más picos que indican el precio de la gasolina por litro
# Aplicar logaritmo y eliminar valores no válidos
log_data = np.log(df['fuel_price_usd_per_l'].dropna())
# KDE
kde = gaussian_kde(log_data)
x_vals = np.linspace(min(log_data), max(log_data), 1000)
y_vals = kde(x_vals)
# Gráfico
plt.figure(figsize=(8, 4))
plt.hist(log_data, bins=30, density=True, alpha=0.4, color='skyblue', label='Histograma (log)')
plt.plot(x_vals, y_vals, color='darkblue', lw=2, label='Densidad KDE')
plt.title('Histograma con curva de densidad (Log precios)')
plt.xlabel('Log(Precio USD por litro)')
plt.ylabel('Densidad')
plt.legend()
plt.grid(True)
plt.show()
Cajas y bigotes#
Un gráfico de cajas y bigotes visualiza la distribución de un conjunto de datos, mostrando la mediana y los cuartiles, así como los posibles outliers.
Características de la cajas y bigotes
Caja: Representa el rango intercuartil (IQR), es decir, el 50% central de los datos, entre el primer y el tercer cuartil (Q1 y Q3).
Línea dentro de la caja: Representa la mediana (Q2) de los datos.
Bigotes: Se extienden desde los cuartiles hasta el valor más pequeño y el más grande dentro de 1.5 veces el IQR. Los valores fuera de este rango se consideran outliers y se marcan como puntos individuales.
Outliers: Valores que caen fuera de los bigotes y son indicados por puntos individuales.
Ventajas
Resúmenes concisos: Muestra un resumen estadístico claro en un formato gráfico compacto.
Detección de outliers: Facilita la identificación de valores atípicos o extremos.
Comparación entre grupos: Permite comparar la distribución de datos entre diferentes grupos o categorías de manera efectiva.
# Ejemplo
Barras#
Una gráfica de barras se utiliza para mostrar y comparar cantidades entre diferentes categorías. Cada barra representa una categoría, y su altura es proporcional al valor que representa.
Características de las barras
Adecuada para datos categóricos.
Las barras pueden organizarse horizontal o verticalmente. Fácil de interpretar y comparar diferentes categorías.
Proporciona una clara visualización de las diferencias entre categorías.
Fácil de leer e interpretar, incluso con muchas categorías.
# Contar el tipo de tienda
# Ejemplo
Circulares#
Un diagrama circular (o gráfico de pastel) es una representación gráfica que muestra la proporción de diferentes categorías dentro de un conjunto de datos como segmentos de un círculo. Cada segmento del círculo representa una categoría y su tamaño es proporcional a su frecuencia o porcentaje en relación con el total.
Características del diagrama circular
Segmentos: Cada porción del círculo corresponde a una categoría y muestra su proporción respecto al total.
Proporciones: La suma de todos los segmentos representa el 100% del conjunto de datos.
Etiquetas: A menudo se etiquetan los segmentos con nombres de categorías y porcentajes.
Ventajas
Visualización clara: Facilita la comprensión de las proporciones de las categorías en un solo vistazo.
Comparación intuitiva: Permite comparar rápidamente las partes del total.
Atractivo visual: Los gráficos de pastel son visualmente atractivos y pueden ser útiles para presentaciones y informes.
Desventaja
Dificultad con muchas categorías: No es ideal para conjuntos de datos con muchas categorías, ya que los segmentos pueden volverse difíciles de distinguir.
Para crear un diagrama circular debemos tener en cuenta los siguientes parámetros:
plt.pie(tipo, labels=tipo.index, autopct='%1.1f%%', startangle=140, colors=plt.cm.Paired(range(len(tipo))))
genera el diagrama circular:
tipocontiene los valores de conteo de cada categoría.labels=tipo.indexasigna etiquetas a cada segmento del gráfico.autopct='%1.1f%%'muestra los porcentajes en cada segmento.startangle=140rota el gráfico para una mejor presentación.colors=plt.cm.Paired(range(len(tipo)))usa un mapa de colores para diferenciar los segmentos.
# Ejemplo
Ahora haremos unas gráficas bivariadas.
Lineas#
Una gráfica de líneas conecta una serie de puntos de datos con líneas, generalmente utilizada para mostrar cambios o tendencias a lo largo del tiempo.
Características del diagrama de lineas
Ideal para series temporales.
Muestra la tendencia general de los datos.
Puede incluir múltiples líneas para comparar diferentes series de datos.
Ventajas
Excelente para visualizar tendencias a lo largo del tiempo.
Permite comparar fácilmente varias series de datos.
Desventajas
Puede volverse confusa si se incluyen demasiadas líneas.
No es adecuada para datos categóricos.
# Ejemplo
Dispersión (Scatter Plots)#
Una gráfica de dispersión muestra la relación entre dos variables numéricas mediante puntos dispersos en un plano cartesiano.
Características del diagrama de dispersión
Muestra cómo se correlacionan dos variables.
Los patrones de dispersión pueden indicar la relación entre las variables, como linealidad o agrupaciones.
Cada punto representa una observación individual.
Ventajas
Ideal para identificar relaciones o correlaciones entre dos variables.
Permite visualizar la distribución y posibles outliers.
Desventajas
No es adecuada para más de dos variables sin técnicas adicionales.
Si hay demasiados puntos, puede volverse difícil de interpretar.
# Crear una gráfica de dispersión de wee
# Ejemplo
Histogramas con variable categórica#
Para hacer estos histogramas debemos tener una variable numérica según una variable categórica
# Ejemplo
Cajas y bigotes con variable categórica#
Para hacer estos diagramas de cajas y bigotes debemos tener una variable numérica según una variable categórica
# Ejemplo
Diagrama de barras con variables categóricas#
Realizaremos un diagrama de barras con dos variables categóricas
# Ejemplo
Para exportar las gráficas en formato png. Usamos savefig:
Este módulo ha proporcionado una base sólida en la importación, manipulación y visualización de datos en Python. Las habilidades adquiridas permitirán crear visualizaciones efectivas que faciliten la interpretación y comunicación de los datos, y la capacidad de manipular y preparar datos adecuadamente es esencial para realizar análisis significativos. La combinación de pandas para la manipulación de datos y Matplotlib para la visualización forma una potente herramienta en el análisis de datos y ciencia de datos.
Diagrama hexagonal#
Existe una versión más elegante de los gráficos de dispersión, llamada hexagonal binning plot (hexbin plot). En este ejercicio, utilizaremos Seaborn para crear una gráfica de dispersión hexagonal (Hexbin Plot) que muestre la relación entre las ventas semanales (weekly_sales) y el precio de la gasolina en USD por litro (fuel_price_usd_per_l). Este gráfico es útil para representar la densidad de datos cuando estos se superponen.
Importemos las bibliotecas necesarias:
import seaborn as sns
import matplotlib.pyplot as plt
Usaremos
sns.scatterplotpara crear una gráfica de dispersión, y añadiremos un esquema de color personalizado para mejorar la visualización.
import warnings
warnings.filterwarnings("ignore", category=FutureWarning)
# Ejemplo
Observación
Este gráfico utiliza celdas hexagonales para representar la densidad de puntos en áreas donde las ventas semanales y el precio de la gasolina están más concentrados.
El histograma en los bordes superior y derecho muestra la variabilidad individual de cada variable (ventas semanales y precio de la gasolina, respectivamente).
Diagrama de contorno#
Los gráficos de contorno son útiles cuando los puntos de datos están densamente poblados en ciertas áreas, ya que muestran la concentración de los datos mediante líneas de contorno. En este ejercicio, crearemos un gráfico de contorno para analizar la relación entre las ventas semanales (weekly_sales) y el precio de la gasolina en USD por litro (fuel_price_usd_per_l).
Importar las bibliotecas necesarias:
import seaborn as sns
import matplotlib.pyplot as plt
Utilizaremos el método
sns.kdeplot()para generar un gráfico de contorno con las ventas semanales y el precio de la gasolina, y rellenar las áreas con gradientes de color para reflejar la densidad de puntos.
import warnings
warnings.filterwarnings("ignore", category=FutureWarning)
# Ejemplo